package cn.lingyangwl.agile.system.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.lingyangwl.agile.model.constants.*;
import cn.lingyangwl.agile.system.assembly.*;
import cn.lingyangwl.agile.system.mapper.*;
import cn.lingyangwl.agile.system.model.entity.*;
import cn.lingyangwl.agile.system.model.rqrs.diy.*;
import cn.lingyangwl.agile.system.service.*;
import cn.lingyangwl.agile.tenant.core.*;
import cn.lingyangwl.framework.data.mate.annotations.*;
import cn.lingyangwl.framework.tool.core.*;
import cn.lingyangwl.framework.tool.core.exception.*;
import cn.lingyangwl.framework.tool.core.tree.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 移动端菜单
 *
 * @author shenguangyang
 */
@Slf4j
@Service
public class DiyAppLinkServiceImpl extends ServiceImpl<DiyAppLinkMapper, DiyAppLink>
    implements IService<DiyAppLink>, DiyAppLinkService {

    @Resource
    private DiyAppLinkAssembly diyAppLinkAssembly;
    
    @Override
    @Tenant(level = DataIsolateLevel.MGT)
    @FieldBindHandle
    public List<DiyAppLinkResp> listLink(DiyAppLinkQueryReq req) {
        LambdaQueryWrapper<DiyAppLink> lqw = DiyAppLink.lqw().orderByAsc(DiyAppLink::getSortNo);

        List<DiyAppLinkResp> flatList = this.list(lqw).stream()
            .map(diyAppLinkAssembly::toLinkResp).collect(Collectors.toList());
        List<DiyAppLinkResp> treeList = TreeUtils.build(flatList, TreeCons.ROOT_PARENT_ID);
        TreeUtils.filter(treeList, (e) -> {
            if (StringUtils.isNotEmpty(req.getName()) && !e.getName().contains(req.getName())) {
               return false;
            }

            return StringUtils.isEmpty(req.getType()) || req.getType().equals(e.getType());
        });

        // 将根节点id设置为nul(适配前端展示)
        treeList.forEach(e -> e.setParentId(null));
        return treeList;
    }

    @Override
    @Tenant(level = DataIsolateLevel.MGT)
    public DiyAppLinkResp getLink(Long id) {
        DiyAppLink entity = this.getById(id);
    	return diyAppLinkAssembly.toLinkResp(entity);
    }

    @Override
    @Tenant(level = DataIsolateLevel.MGT, mustEqMgtScene = true)
    public boolean saveLink(DiyAppLinkSaveReq req) {
        req.setParentId(ObjectUtil.defaultIfNull(req.getParentId(), TreeCons.ROOT_PARENT_ID));
        DiyAppLink entity = diyAppLinkAssembly.toLink(req);

        LambdaQueryWrapper<DiyAppLink> lqw = DiyAppLink.lqw().eq(DiyAppLink::getCode, req.getCode());
        if (StringUtils.isNotEmpty(req.getCode()) && this.count(lqw) > 0) {
            throw new BizException("唯一标识 [{}] 已存在", req.getCode());
        }
    	return this.save(entity);
    }

    @Override
    @Tenant(level = DataIsolateLevel.MGT, mustEqMgtScene = true)
    public boolean updateLink(DiyAppLinkUpdateReq req) {
        DiyAppLink entity = diyAppLinkAssembly.toLink(req);
        LambdaQueryWrapper<DiyAppLink> lqw = DiyAppLink.lqw().ne(DiyAppLink::getId, req.getId())
            .eq(DiyAppLink::getCode, req.getCode());
        if (StringUtils.isNotEmpty(req.getCode()) && this.count(lqw) > 0) {
            throw new BizException("唯一标识 [{}] 已存在", req.getCode());
        }
    	return this.updateById(entity);
    }

    @Override
    @Tenant(level = DataIsolateLevel.MGT, mustEqMgtScene = true)
    public boolean deleteLink(Long id) {
        if (TreeCons.ROOT_PARENT_ID.equals(id)) {
            return false;
        }
        List<Long> deleteIds = new ArrayList<>();
        deleteIds.add(id);

        Map<Long, DiyAppLink> map = this.list().stream().collect(Collectors.toMap(DiyAppLink::getId, Function.identity()));
        DiyAppLink tmp;
        Long nextId = id;
        while ((tmp = map.get(nextId)) != null) {
            deleteIds.add(tmp.getId());
            nextId = tmp.getParentId();
        }
        return this.removeByIds(deleteIds);
    }
    
    @Override
    @Tenant(level = DataIsolateLevel.MGT, mustEqMgtScene = true)
    public boolean batchDeleteLink(List<Long> ids) {
//    	return this.removeByIds(ids);
        return true;
    }
}
